package org.xx.armory.db;

import java.util.Objects;

/**
 * 事务的属性，用于创建新事务。
 *
 * <p>属性概念：</p>
 * <dl>
 * <dt>自动提交</dt>
 * <dd>允许自动提交的事务，如果使用者注销{@link Transaction#revoke(Object)}，那么立刻执行一次提交{@link Transaction#commit()}。</dd>
 * <dt>只读</dt>
 * <dd>只读的事务，在提交时执行回滚，即放弃所有的修改。</dd>
 * <dt>串行化</dt>
 * <dd>串行化的事务，事务级别为{@link java.sql.Connection#TRANSACTION_SERIALIZABLE}，否则是{@link java.sql.Connection#TRANSACTION_READ_COMMITTED}</dd>
 * </dl>
 */
public final class TransactionProperties {
    private final boolean autoCommit;
    private final boolean readOnly;
    private final boolean serializable;

    /**
     * 构造事务属性的实例，默认开启自动提交，只读，无需串行化。
     */
    public TransactionProperties() {
        this(true, true, false);
    }

    /**
     * 构造事务属性的实例。
     *
     * @param autoCommit
     *         是否开启自动提交。
     * @param readOnly
     *         是否只读。
     * @param serializable
     *         是否串行化。
     */
    public TransactionProperties(
            boolean autoCommit,
            boolean readOnly,
            boolean serializable
    ) {
        this.autoCommit = autoCommit;
        this.readOnly = readOnly;
        this.serializable = serializable;
    }

    /**
     * 判断事务是否自动提交。
     *
     * @return 事务是否自动提交。
     */
    public final boolean isAutoCommit() {
        return this.autoCommit;
    }

    /**
     * 判断事务是否只读。
     *
     * @return 事务是否只读。
     */
    public final boolean isReadOnly() {
        return this.readOnly;
    }

    /**
     * 判断事务是否需要串行化。
     *
     * @return 事务是否需要串行化。
     */
    public final boolean isSerializable() {
        return serializable;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return Objects.hash(this.readOnly, this.serializable);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(
            Object obj
    ) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof TransactionProperties)) {
            return false;
        }
        final TransactionProperties other = (TransactionProperties) obj;
        return other.autoCommit == this.autoCommit && other.readOnly == this.readOnly && other.serializable == this.serializable;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "transaction-properties{auto-commit=" + this.autoCommit + ",read-only=" + this.readOnly + ",serializable=" + this.serializable + "}";
    }
}
